// CHECKSTYLE:FileLength:OFF
/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2017 by Hitachi Vantara : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

package org.yzbdl.lanius.www;

import cn.hutool.core.thread.ThreadUtil;
import com.gettyio.core.channel.SocketChannel;
import com.gettyio.core.channel.group.DefaultChannelGroup;
import com.gettyio.core.channel.starter.NioClientStarter;

import java.time.LocalDateTime;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
 * 此类作为Carte双向通讯常量数据存放类
 *
 * @author tanp@yzbdl.ac.cn
 * @since 07-05-2003
 */
public class CarteConst {

    /**
     * Socket消息分隔符
     */
    public static String lineDelimiter = "*#Lanius#Run#Schedule#*";

    /**
     * 启用服务器监控
     */
    public static boolean ENABLE_MONITOR = true;

    /**
     * 定义一个AIO Client
     */
    public static NioClientStarter SOCKET_CLIENT = null;

    /**
     * socket client启动标识
     */
    public static boolean SOCKET_CLIENT_STARTED = false;

    /**
     * 首次建立连接完成标识
     */
    public static boolean FIRST_CONNECT_FINISH = false;

    /**
     * 高优先级 channel Client group 性能较高
     */
    public static DefaultChannelGroup highestPriorityChannelGroup = new DefaultChannelGroup();

    /**
     * 连接成功后的channel Client
     */
    public static DefaultChannelGroup defaultChannelGroup = new DefaultChannelGroup();

    /**
     * 那些繁忙的 client 比如 busy reset
     */
    public static DefaultChannelGroup unhealthyChannelGroup = new DefaultChannelGroup();

    /**
     * 连接成功后的channel Server
     */
    public static SocketChannel nioChannelServer = null;

    /**
     * carte绑定IP
     */
    public static String CARTE_HOST = "localhost";

    /**
     * carte启动端口
     */
    public static int CARTE_PORT = 80;

    /**
     * Carte状态
     */
    public static int CARTE_STATUS = CarteStatus.NORMAL;

    /**
     * Carte状态更新时间
     */
    public static LocalDateTime CARTE_STATUS_UPDATE_TIME = LocalDateTime.now();

    /**
     * Carte状态
     */
    public static class CarteStatus {
        // 空闲  可以被调度
        public static final int FREE = 0;
        // 正常  可以被调度
        public static final int NORMAL = 1;
        // 繁忙  停止调度
        public static final int BUSY = 2;
        // 卡滞  调度并移除队列等待恢复
        public static final int REST = 3;
        // 死亡 (用于schedule)
        public static final int DEAD = 4;
    }

    /**
     * Carte状态枚举
     */
    public enum CarteStatusEnum {
        // 空闲  可以被调度
        FREE("空闲", 0),
        // 正常  可以被调度
        NORMAL("正常", 1),
        // 繁忙  停止调度
        BUSY("繁忙", 2),
        // 卡滞  调度并移除队列等待恢复
        REST("卡滞", 3),
        // 死亡 (用于schedule)
        DEAD("卡滞", 4);

        CarteStatusEnum(String name, Integer value) {
            this.name = name;
            this.value = value;
        }

        // 状态名称
        private String name;
        // 状态值
        private Integer value;

        /**
         * 根据值获取对象
         *
         * @param value
         * @return
         */
        public static CarteStatusEnum getCarteStatusByValue(Integer value) {
            CarteStatusEnum[] alarmGrades = CarteStatusEnum.values();
            for (int i = 0; i < alarmGrades.length; i++) {
                if (alarmGrades[i].getValue().equals(value)) {
                    return alarmGrades[i];
                }
            }
            return null;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getValue() {
            return value;
        }

        public void setValue(Integer value) {
            this.value = value;
        }
    }

    /**
     * 转换作业状态枚举
     * 与Schedule记录状态映射
     */
    public enum TransJobStatusEnum {
        EXEC_ERROR("Exec error", 1),// 执行失败>>执行失败
        FINISHED("Finished", 0),// 完成>>执行成功
        FINISHED_WITH_ERRORS("Finished (with errors)", 1),// 完成带错误>>执行失败
        INIT_TRANS("Initializing", 3),// 初始化中>>初始化中
        INIT_JOB("Waiting", 10),// 等待执行>>初始化中
        PREPARING("Preparing executing", 10),// 准备（等待）执行>>准备（等待）执行
        RUNNING("Running", 4),// 运行中>>运行中
        HALTING("Halting", 4),// 断续运行中>>运行中
        PAUSED("Paused", 8),// 暂停>>暂停
        STOPPED("Stopped", 9);// 停止>>停止（取消执行未加入）

        TransJobStatusEnum(String name, Integer value) {
            this.name = name;
            this.value = value;
        }

        // 状态名称
        private String name;
        // 状态值
        private Integer value;

        /**
         * 根据名称获取对象
         *
         * @param name
         * @return
         */
        public static TransJobStatusEnum getTransJobStatusByName(String name) {
            TransJobStatusEnum[] alarmGrades = TransJobStatusEnum.values();
            for (int i = 0; i < alarmGrades.length; i++) {
                if (alarmGrades[i].getName().equals(name)) {
                    return alarmGrades[i];
                }
            }
            return null;
        }

        /**
         * 根据名称获取对象值
         *
         * @param name
         * @return
         */
        public static String getTransJobStatusValueStrByName(String name) {
            TransJobStatusEnum[] alarmGrades = TransJobStatusEnum.values();
            for (int i = 0; i < alarmGrades.length; i++) {
                if (alarmGrades[i].getName().equals(name)) {
                    return alarmGrades[i].getValue().toString();
                }
            }
            return null;
        }

        /**
         * 根据值获取对象
         *
         * @param value
         * @return
         */
        public static TransJobStatusEnum getTransJobStatusByValue(Integer value) {
            TransJobStatusEnum[] alarmGrades = TransJobStatusEnum.values();
            for (int i = 0; i < alarmGrades.length; i++) {
                if (alarmGrades[i].getValue().equals(value)) {
                    return alarmGrades[i];
                }
            }
            return null;
        }

        /**
         * 根据值获取对象名
         *
         * @param value
         * @return
         */
        public static String getTransJobStatusNameByValue(Integer value) {
            TransJobStatusEnum[] alarmGrades = TransJobStatusEnum.values();
            for (int i = 0; i < alarmGrades.length; i++) {
                if (alarmGrades[i].getValue().equals(value)) {
                    return alarmGrades[i].getName();
                }
            }
            return null;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Integer getValue() {
            return value;
        }

        public void setValue(Integer value) {
            this.value = value;
        }
    }

    /**
     * 定义一个线程池初始化默认值  （cpu+1）
     */
    public static int THREADS_DEFAULT_NUM = Runtime.getRuntime().availableProcessors() + 1;

    /**
     * carte并行任务队列数 默认（cpu+1）
     */
    public static int CARTE_TASK_QUEUE_CORE = CarteConst.THREADS_DEFAULT_NUM;

    /**
     * 任务队列缓冲最大值
     */
    public static int CARTE_TASK_QUEUE_MAX = 256;

    /**
     * 任务队列等待超时设置 10 分钟
     */
    public static int CARTE_QUEUE_WAIT_TIMEOUT = 10;

    /**
     * 多Carte节点模式下超时排队任务将回退，单节点模式会持续排队
     */
    public static boolean MULTI_CARTE_MODE = false;

    /**
     * 启用了双向通讯调度调度模式
     */
    public static boolean WORK_WITH_SOCKET = false;

    /**
     * carte并行任务队列线程池
     */
    public static ThreadPoolExecutor carteTaskPool = null;

    /**
     * 初始化Carte任务队列 空闲线程100毫秒回收
     *
     * @param corePoolSize
     * @param maximumPoolSize
     */
    public static void initCarteTaskPool(Integer corePoolSize, Integer maximumPoolSize) {
//    carteTaskPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, 100l, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10000));
      CarteConst.carteTaskPool = ThreadUtil.newExecutor(corePoolSize, maximumPoolSize);
      CarteConst.carteTaskPool.setKeepAliveTime(100L, TimeUnit.MILLISECONDS);
      CarteConst.carteTaskPool.allowCoreThreadTimeOut(true);
    }


    /**
     * 任务调度次数
     * 避免线程池因为数据库访问引起的滞后问题
     */
    public static int TaskScheduleTimesNow = 0;

}
